table of contents
CLONE(2) | Руководство программиста Linux | CLONE(2) |
ИМЯ¶
clone, __clone2 - создать процесс-потомок
ОБЗОР¶
#define _GNU_SOURCE /* Смотрите feature_test_macros(7) */ #include <sched.h> int clone(int (*fn)(void *), void *child_stack, int flags, void *arg, ... /* pid_t *ptid, struct user_desc *tls, pid_t *ctid */ );
ОПИСАНИЕ¶
clone() создаёт новый процесс как и fork(2). На самом деле это библиотечная функция, использующая системный вызов clone(), который далее будет называться sys_clone. Описание sys_clone приводится в конце данной справочной страницы.
В отличие от fork(2), вышеуказанные вызовы позволяют процессу-потомку использовать некоторые части контекста выполнения вызывающего процесса, такие как: область памяти, таблица файловых дескрипторов и таблица обработчиков сигналов. Заметим, что в данной справочной странице «вызывающий процесс» обычно соответствует «родительскому процессу». Но см. ниже описание CLONE_PARENT.
В основном, вызов clone() используется для реализации нитей: несколько нитей управления в программе, выполняющиеся одновременно в общем пространстве памяти.
Когда процесс-потомок создаётся с помощью clone(), он запускает функцию приложения fn(arg). Это отличается от fork(2), где выполнение продолжается в потомке от точки вызова fork(2). Аргумент fn является указателем на функцию, которая вызывается процессом-потомком в начале своего выполнения. Аргумент arg передаётся функции fn.
Когда происходит возврат из функции приложения fn(arg) процесс-потомок завершается. Целое значение, возвращаемое fn, является кодом выхода процесса-потомка. Процесс-потомок может также быть завершён явным образом с помощью вызова exit(2) или после получения завершающего сигнала.
Аргумент child_stack задаёт положение стека, используемого процессом-потомком. Так как процесс-потомок и вызывающий процесс могут использовать общую память, процесс-потомок не может выполняться в том же стеке, что и вызывающий процесс. Поэтому вызывающий процесс должен установить пространство памяти для стека процесса-потомка и передать указатель на это пространство в вызове clone(). Стеки растут вниз для всех процессоров, на которых работает Linux (за исключением процессоров HP PA), так что child_stack, обычно, указывает на наибольший адрес в пространстве памяти, которое устанавливается для стека процесса-потомка.
Младший байт flags содержит номер сигнала завершения, который посылается родителю, когда работа потомка завершается. Если этот сигнал задаётся как нечто отличное от SIGCHLD, то родительский процесс должен задать параметр __WALL или __WCLONE при ожидании завершения работы потомка с помощью вызова wait(2). Если никакой сигнал не задан, то родительский процесс не извещается сигналом, когда потомок завершается.
Аргумент flags состоит из одной или более данных ниже констант, которые складываются по правилам битового сложения (OR). Флагами задаёт что будет общим между вызывающим процессом и процессом-потомком:
- CLONE_CHILD_CLEARTID (начиная с Linux 2.5.49)
- Стирать идентификатор (ID) нити потомка, расположенный в ctid в памяти потомка, если потомок существует, и активизировать futex по этому адресу. Соответствующий адрес может быть изменён системным вызовом set_tid_address(2). Используется в библиотеках работы с нитями.
- CLONE_CHILD_SETTID (начиная с Linux 2.5.49)
- Сохранить ID нити потомка, расположенный в ctid в памяти потомка.
- CLONE_FILES
- Если задан
флаг CLONE_FILES, то
вызывающий
процесс и
процесс-потомок
используют
одну и ту
же таблицу
файловых
дескрипторов.
Любые
файловые
дескрипторы,
создаваемые
вызывающим
процессом
или
процессом-потомком,
также
доступны и
в другом
процессе.
Аналогично,
если один
из
процессов
закрывает
файловый
дескриптор
или
изменяет
ассоциированные
с ним флаги
(с помощью
fcntl(2)
операцией
F_SETFD), то это
оказывает
влияние и
на другой
процесс.
Если флаг CLONE_FILES не задан, то процесс-потомок наследует копии всех файловых дескрипторов, открытых в вызывающем процессе на момент вызова clone(). Дублируемые файловые дескрипторы в потомке указывают на те же открытые файловые дескрипторы (см. open(2)), соответствующие файловым дескрипторам вызывающего процесса. Операции над файловыми дескрипторами, выполняемые позже вызывающим процессом или процессом-потомком, не оказывают эффекта на другой процесс.
- CLONE_FS
- Если задан
флаг CLONE_FS, то
вызывающий
процесс и
процесс-потомок
используют
одну и ту
же
информацию
о файловой
системе. К
ней
относится
корневой
каталог
файловой
системы,
текущий
рабочий
каталог и
значение umask.
Любой
вызов, chroot(2),
chdir(2) или umask(2),
выполняемый
одним
процессом,
оказывает
влияние и
на другой.
Если флаг CLONE_FS не задан, то процесс-потомок работает с копией информации о файловой системе вызывающего процесса, снятой на момент вызова clone(). Вызовы chroot(2), chdir(2), umask(2), выполняемые позже одним из процессов, не оказывают эффект на другой процесс.
- CLONE_IO (начиная Linux 2.6.25)
- Если задан
флаг CLONE_IO, то
новый
процесс
использует
общий
контекст
ввода-вывода
с
вызывающим
процессом.
Если этот
флаг не
установлен,
то (как и в
fork(2)) новый
процесс
будет
иметь свой
отдельный
контекст
ввода-вывода.
Контекст ввода-вывода — это область ввода-вывода в дисковом планировщике (т.е то, что планировщик ввода-вывода использует при планировании ввода-вывода процесса). Если процессы используют общий контекст ввода-вывода, то они рассматриваются планировщиком ввода-вывода как один. Следовательно, они совместно делят время доступа к диску. У некоторых планировщиков ввода-вывода, если два процесса используют общий контекст ввода-вывода, то им будет разрешено чередовать доступ к диску. Если несколько нитей выполняют ввод-вывод из одного процесса (например, aio_read(3)), то для них нужно указать CLONE_IO для получения большей производительности ввода-вывода.
Если в ядре не указан параметр сборки CONFIG_BLOCK, то этот флаг ни на что не влияет.
- CLONE_NEWIPC (начиная с Linux 2.6.19)
- Если задан
флаг CLONE_NEWIPC, то
процесс
создаётся
в новом
пространстве
имён IPC. Если
этот флаг
не
установлен,
то (как и в
fork(2)) процесс
создаётся
в том же
пространстве
имён IPC что и
вызывающий
процесс.
Этот флаг
предназначен
для
реализации
контейнеров.
Пространство имён IPC состоит из набора идентификаторов объектов System V IPC. (Эти объекты создаются с помощью msgctl(2), semctl(2) и shmctl(2)). Объекты, созданные в пространстве имён IPC, видимы всем другим процессам, которые являются членами этого пространства имён, и невидимы процессам из других пространств имён IPC.
При уничтожении пространства имён IPC (т.е, когда завершается последний процесс из этого пространства имён), все объекты IPC из пространства имён автоматически уничтожаются.
Для использования этого флага требуется: ядро, собранное с параметрами CONFIG_SYSVIPC и CONFIG_IPC_NS, и процесс должен иметь мандат (CAP_SYS_ADMIN). Этот флаг не может указываться одновременно с CLONE_SYSVSEM.
- CLONE_NEWNET (начиная с Linux 2.6.24)
- (Реализация
этого
флага
завершена
в Linux 2.6.29.)
Если задан флаг CLONE_NEWNET, то процесс создаётся в новом сетевом пространстве имён. Если флаг не установлен, то (как и в fork(2)), процесс создаётся в том же сетевом пространстве имён что и вызывающий процесс. Этот флаг предназначен для реализации контейнеров.
Сетевое пространство имён предоставляет изолированное представление сетевого стека (интерфейсы сетевых устройств, стеки протоколов IPv4 и IPv6, таблицы маршрутизации IP, правила межсетевого экрана, дерево каталогов /proc/net и /sys/class/net, сокеты и т.д.). Физическое сетевое устройство может находиться только в одном сетевом пространстве имён. Пара виртуальных сетевых устройств ("veth") предоставляет каналоподобную абстракцию, которую можно использовать для создания туннелей между сетевыми пространствами имён и создания моста к физическому сетевому устройству из другого пространства имён.
Когда сетевое пространство имён высвобождается (т.е., когда завершается последний процесс в пространстве имён), его физические сетевые устройства перемещаются обратно в первоначальное сетевое пространство имён (не родительского процесса).
Для работы флага требуется: ядро, собранное с параметром CONFIG_NET_NS, и привилегированный процесс (CAP_SYS_ADMIN).
- CLONE_NEWNS (начиная с Linux 2.4.19)
- Запускает
потомка в
новом
пространстве
имён
монтирования.
Каждый процесс живёт в некотором пространстве имён монтирования. Пространство имён процесса — это данные (список смонтированных файловых систем), описывающие иерархию файлов, видимую этим процессом. После вызова fork(2) или clone(), если не установлен флаг CLONE_NEWNS, потомок живёт в том же пространстве имён монтирования что и родитель. Системные вызовы mount(2) и umount(2) изменяют пространство имён монтирования вызывающего процесса и, следовательно, влияют на все процессы, которые живут в этом же пространстве имён, но не влияют на процессы в других пространствах имён монтирования.
После вызова clone() с установленным флагом CLONE_NEWNS потомок запускается в новом пространстве имён монтирования, инициализированном копией пространства имён родителя.
Только привилегированный процесс (имеющий мандат CAP_SYS_ADMIN) может задавать флаг CLONE_NEWNS. Не допускается совместное использование флагов CLONE_NEWNS и CLONE_FS в одном вызове clone().
- CLONE_NEWPID (начиная с Linux 2.6.24)
- Если задан
флаг CLONE_NEWPID, то
процесс
создаётся
в новом
пространстве
имён PID. Если
флаг не
установлен,
то (как и в
fork(2)), процесс
создаётся
в том же
пространстве
имён PID, что и
вызывающий
процесс.
Этот флаг
предназначен
для
реализации
контейнеров.
Пространство имён PID предоставляет изолированное окружение для идентификаторов (PID): идентификаторы в новом пространстве имён начинаются с 1 как в автономной системе, и вызовы fork(2), vfork(2) или clone(2) будут создавать процессы с уникальными идентификаторами в пределах пространства имён.
Первый созданный процесс в новом пространстве имён (т.е., процесс, созданный с флагом CLONE_NEWPID) имеет PID 1, и является "начальным" процессом в пространстве имён. Потомкам, теряющим родителей в этом пространстве имён, будет переназначен этот процесс, а не init(8). В отличие от обычного процесса init, "начальный" процесс пространства имён PID может завершиться и если это произойдёт, то все процессы в этом пространстве имён также завершатся.
Пространства имён PID образуют иерархию. Когда создаётся новое пространство имён PID, процессы в этом пространстве видимы в пространстве имён PID процесса, который создал это новое пространство имён; аналогично, если родитель пространства имён PID сам является потомком другого пространства имён PID, то процессы в пространстве имён PID потомка и родителя будут видимы в прародительском пространстве имён PID. И наоборот, процессы в "дочернем" пространстве имён PID не видят процессы в родительском пространстве имён. Существование иерархии пространства имён означает, что каждый процесс теперь может иметь несколько PID — один на каждое пространство имён, в котором он видим; каждый из этих PID уникален внутри соответствующего пространства имён. Вызов getpid(2) всегда возвращает PID, связанный с пространством имён, в котором находится процесс.
После создания нового пространства имён для потомка полезно изменить свой корневой каталог и примонтировать новый экземпляр procfs в каталог /proc так, чтобы различные инструменты, например ps(1), работали правильно. (Если в flags также установлен CLONE_NEWNS, то нет необходимости изменять корневой каталог: новый экземпляр procfs можно смонтировать непосредственно поверх /proc.)
Для использования флага требуется: ядро, собранное с параметром CONFIG_PID_NS и привилегированный процесс (CAP_SYS_ADMIN). Данный флаг не может указываться вместе с CLONE_THREAD.
- CLONE_NEWUTS (начиная с Linux 2.6.19)
- Если задан
флаг CLONE_NEWUTS, то
процесс
создаётся
в новом
пространстве
имён UTS, чьи
идентификаторы
инициализируются
копией
идентификаторов
из
пространства
имён UTS
вызывающего
процесса.
Если флаг
не указан,
то (как и в
fork(2)), процесс
создаётся
в том же
пространстве
имён UTS что и
вызывающий
процесс.
Этот флаг
предназначен
для
реализации
контейнеров.
Пространство имён UTS — это набор идентификаторов, возвращаемых uname(2); помимо остальных, сюда включены доменное имя и имя узла, которые изменить с помощью setdomainname(2) и sethostname(2), соответственно. Изменившиеся идентификаторы в пространстве имён UTS видимы всем остальным процессам в том же пространстве имён, но не видимы процессам из других пространств имён UTS.
Для этого флага требуется: ядро, собранное с параметром CONFIG_UTS_NS и привилегированный процесс (CAP_SYS_ADMIN).
- CLONE_PARENT (начиная с Linux 2.3.12)
- Если задан
флаг CLONE_PARENT, то
родитель
нового
потомка
(возвращаемый
getppid(2)) будет
таким же
как и у
вызывающего
процесса.
Если флаг CLONE_PARENT не задан, то (как и в fork(2)) родителем будет вызывающий процесс.
Заметим, что это тот родительский процесс, который возвращается вызовом getppid(2), и которому приходит сигнал когда потомок завершается, так что если указан флаг CLONE_PARENT, то сигнал будет посылаться родителю вызывающего процесса, а не самому вызывающему процессу.
- CLONE_PARENT_SETTID (начиная с Linux 2.5.49)
- Сохраняет ID нити потомка в расположение ptid в память родителя и потомка. (В Linux 2.5.32-2.5.48 был флаг CLONE_SETTID, который делал это.)
- CLONE_PID (устарел)
- Если задан флаг CLONE_PID, то процесс-потомок создаётся с таким же идентификатором процесса (ID) как и вызывающий процесс. Это хорошо для ковыряния в системе, но не более того. Начиная с 2.3.21 этот флаг может быть указан только в системном загрузочном процессе (PID 0). Флаг удалён в Linux 2.5.16.
- CLONE_PTRACE
- Если задан флаг CLONE_PTRACE и вызывающий процесс находится в режиме трассировки, то процесс-потомок также будет работать в режиме трассировки (см. ptrace(2)).
- CLONE_SETTLS (начиная с Linux 2.5.32)
- Аргумент newtls содержит новый дескриптор TLS (локальная память нитей). (См. set_thread_area(2).)
- CLONE_SIGHAND
- Если задан
флаг CLONE_SIGHAND, то
вызывающий
процесс и
процесс-потомок
используют
одну и ту
же таблицу
обработчиков
сигналов.
Если
вызывающий
процесс
или
процесс-потомок
вызывают
sigaction(2) для
изменения
поведения
при
получении
сигнала, то
это
поведение
изменяется
также и в
другом
процессе.
Однако,
вызывающий
процесс и
процесс-потомок
имеют
различные
маски
сигналов и
списки
ожидающих
обработки
сигналов.
Так, один
из них
может
блокировать
или
деблокировать
некоторые
сигналы,
используя
sigprocmask(2), и это не
будет
влиять на
другой
процесс.
Если флаг CLONE_SIGHAND не указан, то процесс-потомок наследует копию обработчиков событий вызывающего процесса, снятую на момент вызова clone(). Вызовы sigaction(2), выполняемые позже одним из процессов, не оказывают влияния на другой процесс.
Начиная с Linux 2.6.0-test6, flags должен также включать CLONE_VM, если указан CLONE_SIGHAND.
- CLONE_STOPPED (начиная с Linux 2.6.0-test2)
- Если
указан
флаг CLONE_STOPPED, то
после
создания
потомок
перейдёт в
состояние
останова
(как если
бы ему
послали
сигнал SIGSTOP), и
начнёт
работу по
сигналу SIGCONT.
Этот флаг устарел начиная с Linux 2.6.25 и был удалён в Linux 2.6.38.
- CLONE_SYSVSEM (начиная с Linux 2.5.10)
- Если указан флаг CLONE_SYSVSEM, то потомок и вызывающий процесс будут использовать общий список значений undo для семафоров System V (смотрите semop(2)). Если флаг не указан, то потомок получит отдельный список undo, который изначально пуст.
- CLONE_THREAD (начиная с Linux 2.4.0-test8)
- Если
указан
флаг CLONE_THREAD, то
потомок
размещается
в той же
группе
нитей, что
и
вызывающий
процесс.
Чтобы
сделать
остаток
обсуждения
CLONE_THREAD более
понятным,
термин
"нить"
используется
для ссылки
на
процессы
внутри
группы
нитей.
Группы нитей были добавлены в Linux 2.4 для поддержки нитей POSIX, описываемых как набор нитей, использующих один и тот же PID. Внутренне общий PID — это так называемый идентификатор группы нитей (TGID). Начиная с Linux 2.4, вызов getpid(2) возвращает идентификатор группы нитей вызывающего процесса.
Внутри группы нити можно различать по их (глобальному) уникальному идентификатору нити (TID). TID новой нити возвращается вызывающему как результат clone(), а нить может узнать свой TID с помощью вызова gettid(2).
Когда вызов clone() делается без CLONE_THREAD, то получаемая нить помещается в новую группу нитей, чей TGID совпадает с TID нити. Эта нить будет лидером новой группы нитей.
Новая нить, созданная с CLONE_THREAD, имеет тот же родительский процесс что и вызвавший clone() (т.е., как CLONE_PARENT), поэтому при вызове getppid(2) возвращается одинаковое значение для всех нитей в группе нитей. Когда нить CLONE_THREAD завершается, нити, создавшей её с помощью clone(), не посылается сигнал SIGCHLD (или другой сигнал завершения); состояние такой нити нельзя получить с помощью wait(2). Про нить говорят, что она отсоединена (detached).
После завершения работы всех нитей в группе нитей родительскому процессу группы нитей посылается сигнал SIGCHLD (или другой завершающий сигнал).
Если в любой из нитей группы нитей выполняется вызов execve(2), то все нити отличные от лидера группы нитей, завершаются и выполняется новая программы в лидере группы нитей.
Если одна из нитей группы нитей создаёт потомка с помощью fork(2), то любая нить группы может вызвать wait(2) для ожидания этого потомка.
Начиная с Linux 2.5.35, аргумент flags должен также включать CLONE_SIGHAND, если указан флаг CLONE_THREAD.
Сигналы могут посылаться как всей группе (т.е., TGID) с помощью kill, так и заданной нити (т.е., TID) с помощью tgkill(2).
Расположение и действия сигналов распространяются на весь процесс: если необработанный сигнал доставляется нити, то это влияет (завершение, остановка, продолжение, игнорирование) на все члены группы нитей.
Каждая нить имеет свою маску сигналов, задаваемую с помощью sigprocmask(2), но сигналы могут ожидать обработки: всем процессом (т.е., доставляются всем членам группы нитей), если посылаются с помощью kill(2); или отдельной нитью, если посылаются с помощью tgkill(2). Вызов sigpending(2) возвращает набор сигналов, который представляет собой объединение ожидающих сигналов для всего процесса и сигналов, которые ожидает вызывающая нить.
Если для отправки сигнала группе нитей используется kill(2) и у группы нитей установлен обработчик сигнала, то обработчик будет вызван только один раз в произвольно выбранном члене группы нитей, который не блокирует сигнал. Если несколько нитей в группе ждут приёма того же сигнала с помощью sigwaitinfo(2), то ядро произвольно выберет одну из этих нитей для приёма сигнала, отправленного с помощью kill(2).
- CLONE_UNTRACED (начиная с Linux 2.5.46)
- Если указан флаг CLONE_UNTRACED, то выполняющий трассировку процесс не сможет указать CLONE_PTRACE на этом процессе-потомке.
- CLONE_VFORK
- Если
указан
флаг CLONE_VFORK, то
выполнение
вызывающего
процесса
приостанавливается
до тех пор,
пока
потомок не
освободит
ресурсы
виртуальной
памяти с
помощь
вызова execve(2)
или _exit(2) (как
с vfork(2)).
Если флаг CLONE_VFORK не указан, то вызывающий процесс и потомок доступны для планирования после вызова, и приложение не должно полагаться на то, что выполнение производится в каком-то определённом порядке.
- CLONE_VM
- Если задан
флаг CLONE_VM, то
вызывающий
и дочерний
процесс
работают в
одном
пространстве
памяти. В
частности,
запись в
память
одним
процессом
видна
другому.
Кроме того,
выполнение
отображения
или снятия
отображения
в память,
выполняемая
с помощью
mmap(2) или munmap(2),
одним
процессом,
влияет на
другой.
Если флаг CLONE_VM не установлен, то дочерний процесс выполняется в отдельной копии пространства памяти вызывающего процесс с момента clone(). Запись в память или отображение/снятие отображения файла, выполняемое одним процессом, не влияет на другой (как с fork(2)).
sys_clone¶
Системный вызов sys_clone больше похож на fork(2) в том плане, что выполнение в потомке продолжается от места данного вызова. Таким образом sys_clone требует только аргументы flags и child_stack, которые имеют то же значение что и для вызова clone(). Заметим, что порядок этих аргументов отличается от clone().
Другое отличие sys_clone состоит в том, что аргумент child_stack может быть нулём, в этом случае семантика копирование-при-записи обеспечивает получение потомком отдельных копий страниц стека, когда один из процессов изменяет стек. В этом случае для правильной работы не должен быть задан флаг CLONE_VM.
В Linux 2.4 и более ранних clone() не принимал аргументов ptid, tls и ctid.
ВОЗВРАЩАЕМОЕ ЗНАЧЕНИЕ¶
При успешном выполнении в вызывающую исполняемую нить возвращается ID нити дочернего процесса. Иначе в контекст вызывающего возвращается -1, дочерний процесс не создаётся и errno устанавливается в соответствующее значение.
ОШИБКИ¶
- EAGAIN
- Уже выполняется максимальное количество процессов.
- EINVAL
- Указан флаг CLONE_SIGHAND, но нет CLONE_VM (начиная с Linux 2.6.0-test6).
- EINVAL
- Указан флаг CLONE_THREAD, но нет CLONE_SIGHAND (начиная с Linux 2.5.35).
- EINVAL
- Указаны оба флага, CLONE_FS и CLONE_NEWNS, в flags.
- EINVAL
- Указаны оба флага, CLONE_NEWIPC и CLONE_SYSVSEM, в flags.
- EINVAL
- Указаны оба флага, CLONE_NEWPID и CLONE_THREAD, в flags.
- EINVAL
- Возвращается clone(), если child_stack равен нулю.
- EINVAL
- Указан флаг CLONE_NEWIPC в flags, но ядро собрано без параметров CONFIG_SYSVIPC и CONFIG_IPC_NS.
- EINVAL
- Указан флаг CLONE_NEWNET в flags, но ядро собрано без параметра CONFIG_NET_NS.
- EINVAL
- Указан флаг CLONE_NEWPID в flags, но ядро собрано без параметра CONFIG_PID_NS.
- EINVAL
- Указан флаг CLONE_NEWUTS в flags, но ядро собрано без параметра CONFIG_UTS.
- ENOMEM
- Не удалось выделить достаточно памяти для структуры задач потомка или скопировать необходимые части контекста вызывающего.
- EPERM
- Указан флаг CLONE_NEWIPC, CLONE_NEWNET, CLONE_NEWNS, CLONE_NEWPID, или CLONE_NEWUTS, но процесс не имеет достаточно прав (нет мандата CAP_SYS_ADMIN).
- EPERM
- Указан флаг CLONE_PID, но ID процесса не равен 0.
ВЕРСИИ¶
Вызов clone() отсутствует в libc5. В glibc2 есть clone(), который соответствует данному описанию.
СООТВЕТСТВИЕ СТАНДАРТАМ¶
Вызовы clone() и sys_clone есть только в Linux и не должны использовать в переносимых программах.
ЗАМЕЧАНИЯ¶
Для ядер версий 2.4.x флаг CLONE_THREAD не делает родителем новой нити того же родителя что и у вызывающего процесса. Однако для ядер версий 2.4.7-2.4.18 флаг CLONE_THREAD неявно подразумевает флаг CLONE_PARENT (как в ядре 2.6).
Некоторое время существовал флаг CLONE_DETACHED (начиная с 2.5.32): родитель не хочет получать сигнал завершения потомка. В версии 2.6.2 это стало действием по умолчанию и флаг CLONE_THREAD был убран. Этот флаг ещё определён, но не оказывает никакого действия.
На архитектуре i386 clone() не должен вызываться через vsyscall, а запускаться явно с помощью int $0x80.
На ia64 используется другой системный вызов:
int __clone2(int (*fn)(void *), void *child_stack_base, size_t stack_size, int flags, void *arg, ... /* pid_t *ptid, struct user_desc *tls, pid_t *ctid */ );
Системный вызов __clone2() работает также как и clone() за исключением того, что child_stack_base указывает на самый нижний адрес области стека потомка, и в stack_size задаётся размер стека, указываемого в child_stack_base.
ДЕФЕКТЫ¶
Версии библиотеки GNU C, которые включают библиотеку нитей NPTL, содержат обёрточную функцию getpid(2), которая выполняет кэширование PID. Это кэширование полагается на поддержку обёртки glibc для clone(), но, согласно имеющейся реализации, в некоторых случаях кэш может содержать неактуальные данные. В частности, если сигнал доставляется потомку сразу после вызова clone(), то вызов getpid(2) в обработчике сигнала может может вернуть PID вызывающего процесса («родителя»), если у обёртки clone ещё не было возможности обновить кэш PID в потомке. (В этом описании не рассматривается случай где потомок был создан с использованием флага CLONE_THREAD, когда getpid(2) должен вернуть одинаковое значение и в потомок и в процесс, который вызвал clone(), так как вызывающий и потомок находятся в одной группе нитей. Также проблема устаревания кэша возникает, если аргумент flags содержит CLONE_VM.) Чтобы получить правильное значение, может потребоваться использовать следующий код:
#include <syscall.h>
pid_t mypid;
mypid = syscall(SYS_getpid);
СМОТРИТЕ ТАКЖЕ¶
fork(2), futex(2), getpid(2), gettid(2), set_thread_area(2), set_tid_address(2), tkill(2), unshare(2), wait(2), capabilities(7), pthreads(7)
2011-09-08 | Linux |